home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Monster Media 1994 #2
/
Monster Media No. 2 (Monster Media)(1994).ISO
/
clipper
/
tcmclp.zip
/
TCMCLIP.PRG
< prev
Wrap
Text File
|
1994-05-21
|
39KB
|
1,312 lines
*┌──────────────────────────────────────────────────────────────────────────┐
*│ TCMCLIP Version 1.01 Created: 12/09/87 Revised: 05/21/94 │
*│ │
*│ Author: Todd C. MacDonald Compuserve ID: 72274,2252 │
*└──────────────────────────────────────────────────────────────────────────┘
*
* The is an original work by Todd C. MacDonald and is hereby placed in the
* public domain.
*
* As of 5/21/94, this file had 976 downloads from CIS and still counting.
* Though this code may have been "good" for it's time, I certainly wouldn't
* recommend it for a 5.x programmer. At any rate, seeing as people are still
* downloading it, I modified it strictly to make it compatible with Clipper
* 5.x. It is still Summer '87 code, however. I also removed the restrictions
* I had placed on the previous version.
*
* This program demonstrates the use of some routines for menus & windows &
* this & that for Clipper Summer '87 applications. You may freely use and
* distribute this code as you see fit.
*
* ─────────────────────────────── A few notes ───────────────────────────────
*
* Some routines require one of the SCRNPLAY functions. They are available
* from their author and are also public domain:
*
* Rick Whitt, SysOp
* dBoard BBS - Winston-Salem, NC
* (919) 768-3043
*
* In S'87, I prefaced variable names according to their scope or purpose:
*
* a = array (private or public)
* f = file variable
* p = public memory variable
* l = local (any variable not of the other types)
*
* I call procedures with the same syntax as a function (The compiler doesn't
* care and "DO xyz WITH" is too wordy for me.
*
* Clipper is a trademark of Computer Associates and is copyrighted and all
* that jazz...
*
* ─────────────────────────── On with the demo... ───────────────────────────
*
* To compile and link this demo program, type the following:
*
* C> CLIPPER TCMCLIP
* C> TLINK TCMCLIP+CHGATTR,,,CLIPPER+EXTEND
* -OR-
* LINK TCMCLIP+CHGATTR,,,CLIPPER+EXTEND
* -OR-
* PLINK86 FI TCMCLIP,CHGATTR LIB CLIPPER,EXTEND
* -OR-
* RTLINK FI TCMCLIP,CHGATTR
* -OR-
* BLINKER FI TCMCLIP,CHGATTR
*
* To run the demo:
*
* C> TCMCLIP
*
*
* ───────────────────────── demo source begins here ──────────────────────────
* Get the starting time
lStartTime=time()
* set up the environment
set cursor off
set scoreboard off
set bell off
set escape on
* Keystroke mnemonics
kNull = 0
kEnter = 13
kBackSpace = 8
kEsc = 27
kHome = 1
kEnd = 6
kPgUp = 18
kPgDn = 3
kUArrow = 5
kDArrow = 24
kLArrow = 19
kRArrow = 4
kInsert = 22
kTab = 9
kCtrlHome = 29
kCtrlEnd = 23
kCtrlPgUp = 31
kCtrlPgDn = 30
kF2 = -1
kF3 = -2
kF4 = -3
kF5 = -4
kF6 = -5
kF7 = -6
kF8 = -7
kF9 = -8
kF10 = -9
* Set up the windowing variables
lMaxWinds = 5
public aWindColor[lMaxWinds], aWindow[lMaxWinds]
public aWindT[lMaxWinds], aWindL[lMaxWinds], aWindB[lMaxWinds], aWindR[lMaxWinds]
public pWindIndex, pWindFrame, pShadow, pExplode, pExpFactor, pExpDelay
pWindIndex = 0 && Used by windowing routines to keep track of windows
pWindFrame = '┌─╖║╝═╘│ ' && Default window frame characters
pShadow = .t. && .t. to paint shadows around windows, .f. otherwise
pExplode = .t. && .t. for exploding windows, .f. otherwise
pExpFactor = 1 && lower for more "stages" in the explosion, higher for less
pExpDelay = 0 && increase this to slow down the exploding effect
* Summer '87 doesn't provide windows so we have to do our own relative addressing
lLogoT = 14
lLogoL = 43
lLogoB = lLogoT+8
lLogoR = lLogoL+34
lMenuT = 1
lMenuL = 2
lMenuB = lMenuT+6
lMenuR = lMenuL+39
lCloseT = 1
lCloseL = 2
lCloseB = lCloseT+8
lCloseR = lCloseL+35
* Define colors
if iscolor()
lBackGrnd = "W+/B"
pHelpColor = "W/N"
pHelpHigh = "GR+/N"
pHelpHighF = 14
pHelpHighB = 0
lLogo = "N/W"
lMenuFrame = "BG/B"
lMenuHead = "BG+/B"
lMenuBody = "W/B"
lMnuNorm = "W/B"
lMnuHilite = "W/RB"
lMenuSelF = 14
lMnuSelB = 1
lMnuSelFHi = 14
lMnuSelBHi = 5
pErrFrame = "R+/R"
pErrHead = "GR+*/R"
pErrBody = "W+/R"
lClosFrame = "W/GR"
lClosHead = "W/GR"
lClosBody = "N/GR,GR+*/GR"
else
lBackGrnd = "W+/N"
pHelpColor = "W/N"
pHelpHigh = "W+/N"
pHelpHighF = 15
pHelpHighB = 0
lLogo = "N/W"
lMenuFrame = "W+/N"
lMenuHead = "W+/N"
lMenuBody = "W/N,N/W,,,W+/N"
lMnuNorm = "W/N"
lMnuHilite = "N/W"
lMenuSelF = 15
lMnuSelB = 0
lMnuSelFHi = 0
lMnuSelBHi = 7
pErrFrame = "N/W"
pErrHead = "N*/W"
pErrBody = "W/N,N/W,,,W+/N"
lClosFrame = "W+/N"
lClosHead = "W+/N"
lClosBody = "W/N,W+*/N"
endif
* Make things pretty
lBGchar = '░'
clear
set color to (lBackGrnd)
@ 0, 0, 23, 79 box replicate(lBGchar, 9)
DispLogo()
* Whew! Let's go already...
lChoice = 1
do while .t.
OpenWindow(lMenuT, lMenuL, lMenuB, lMenuR, lMenuFrame, lMenuHead, lMenuBody, 'BY YOUR COMMAND', .f.)
HelpMsg('Use '+chr(25)+chr(24)+' to highlight option and press Enter; or type capital letter of Option')
InitMenu(5, lMnuNorm, lMnuHilite, lMenuSelF, lMnuSelB, lMnuSelFHi, lMnuSelBHi)
MenuPrompt(lMenuT+01, lMenuL+01, ' okay, show me the Windows ', 20)
MenuPrompt(lMenuT+02, lMenuL+01, [ what's this "thermometer Bar" thing? ], 27)
MenuPrompt(lMenuT+03, lMenuL+01, ' yeah, so what about the Menus? ', 26)
MenuPrompt(lMenuT+04, lMenuL+01, ' Is that all there is? ', 2)
MenuPrompt(lMenuT+05, lMenuL+01, ' get me Outta here ', 9)
lChoice = MenuChoice(lChoice )
do case
case lChoice = 1
ClosWindow()
EraseLogo()
WindowDemo()
DispLogo()
case lChoice = 2
ClosWindow()
EraseLogo()
BarDemo()
DispLogo()
case lChoice = 3
Error([Whata'ya mean "what about the menus?" You've been using them all along!])
ClosWindow()
case lChoice = 4
ClosWindow()
EraseLogo()
IsThatAll()
DispLogo()
case lChoice = 5
ClosWindow()
ClosSystem()
exit
otherwise
lChoice = 5
ClosWindow()
endcase
enddo
* Clean up and go home
set color to
@ 24, 00
@ 23, 00 say ''
set cursor on
quit
*
procedure WindowDemo
*------------------*
lOptT = 5
lOptL = 10
lOptB = lOptT+5
lOptR = lOptL+30
lWind1T = 1
lWind1L = 2
lWind1B = 21
lWind1R = 75
lWind2T = 3
lWind2L = 40
lWind2B = 17
lWind2R = 71
lWind3T = 5
lWind3L = 7
lWind3B = 7
lWind3R = 65
lWind4T = 10
lWind4L = 4
lWind4B = 19
lWind4R = 37
lWind5T = 4
lWind5L = 10
lWind5B = 14
lWind5R = 21
lExplode = pExplode
lExpFactor = pExpFactor
lExpDelay = pExpDelay
lShadow = pShadow
if iscolor()
lOptFrame = 'W+/BG'
lOptHead = 'N/BG'
lOptBody = 'B/BG,GR+/B,,,GR+/BG'
lWn1Frame = 'G+/B'
lWn1Head = 'GR+/B'
lWn1Body = 'N/B'
lWn2Frame = 'W+/BG'
lWn2Head = 'N/BG'
lWn2Body = 'B/BG'
lWn3Frame = 'W/RB'
lWn3Head = 'GR+/RB'
lWn3Body = 'N/W'
lWn4Frame = 'GR+/G'
lWn4Head = 'W+/G'
lWn4Body = 'N/G'
lWn5Frame = 'W+/R'
lWn5Head = 'BG+/R'
lWn5Body = 'N/R'
else
lOptFrame = 'W/N'
lOptHead = 'W+/N'
lOptBody = 'W/N,N/W,,,W+/N'
lWn1Frame = 'W/N'
lWn1Head = 'W+/N'
lWn1Body = 'W/N,N/W,,,W+/N'
lWn2Frame = 'W/N'
lWn2Head = 'W+/N'
lWn2Body = 'W/N,N/W,,,W+/N'
lWn3Frame = 'W/N'
lWn3Head = 'W+/N'
lWn3Body = 'W/N,N/W,,,W+/N'
lWn4Frame = 'W/N'
lWn4Head = 'W+/N'
lWn4Body = 'W/N,N/W,,,W+/N'
lWn5Frame = 'W/N'
lWn5Head = 'W+/N'
lWn5Body = 'W/N,N/W,,,W+/N'
endif
OpenWindow(lOptT, lOptL, lOptB, lOptR, lOptFrame, lOptHead, lOptBody, 'WINDOW OPTIONS')
do while .t.
@ lOptT+1, lOptL+2 say 'Exploding windows: (Y/N)'
@ lOptT+2, lOptL+3 say 'Explosion factor: (1-4)'
@ lOptT+3, lOptL+4 say 'Explosion delay: (1-99)'
@ lOptT+4, lOptL+3 say 'Shadowed windows: (Y/N)'
@ lOptT+1, lOptL+21 get pExplode pict 'Y'
@ lOptT+2, lOptL+21 get pExpFactor pict '9' range 1,4
@ lOptT+3, lOptL+21 get pExpDelay pict '99' range 1,99
@ lOptT+4, lOptL+21 get pShadow pict 'Y'
HelpMsg('PgDn-Done Esc-Abort')
ReadGets()
if lastkey() = kEsc
ClosWindow()
exit
endif
if Verify('Are the options set the way you want them? [Y/n]')
ClosWindow()
OpenWindow(lWind1T, lWind1L, lWind1B, lWind1R, lWn1Frame, lWn1Head, lWn1Body, 'WINDOW 1')
OpenWindow(lWind2T, lWind2L, lWind2B, lWind2R, lWn2Frame, lWn2Head, lWn2Body, 'WINDOW 2')
OpenWindow(lWind3T, lWind3L, lWind3B, lWind3R, lWn3Frame, lWn3Head, lWn3Body, 'WINDOW 3')
OpenWindow(lWind4T, lWind4L, lWind4B, lWind4R, lWn4Frame, lWn4Head, lWn4Body, 'WINDOW 4')
OpenWindow(lWind5T, lWind5L, lWind5B, lWind5R, lWn5Frame, lWn5Head, lWn5Body, 'WINDOW 5')
HelpMsg('Press any key...')
inkey(0)
ClosWindow()
ClosWindow()
ClosWindow()
ClosWindow()
ClosWindow()
exit
endif
if lastkey() = kEsc
ClosWindow()
exit
endif
enddo
pExplode = lExplode
pExpFactor = lExpFactor
pExpDelay = lExpDelay
pShadow = lShadow
return
*
procedure BarDemo
*---------------*
private lTop, lLeft, lBottom, lRight, lFramColor, lHeadColor, lBodyColor
private lScalColor, lBarColor, I, lLoopCount
lTop = 7
lLeft = 33
lBottom = lTop + 4
lRight = lLeft + 35
if iscolor()
lFramColor = 'W/RB'
lHeadColor = 'W+/RB'
lBodyColor = 'N/RB,GR+/RB'
lScalColor = 'W/RB'
lBarColor = 'W+/RB'
else
lFramColor = 'W+/N'
lHeadColor = 'W+/N'
lBodyColor = 'W/N,N/W,,,W+/N'
lScalColor = 'W/N'
lBarColor = 'W/N'
endif
OpenWindow(lTop, lLeft, lBottom, lRight, lFramColor, lHeadColor, lBodyColor,;
'Percentage Complete Bar Demo')
@ lTop+1, lLeft+2 say 'Iteration: Complete'
* Initialize and draw the bar scale
InitBar(lTop+3, lLeft+2, 32, lScalColor, lBarColor)
setcolor(GetColor(5))
* Initialize the denominator ( Hint: This could be RECCOUNT() )
lLoopCount = 250
* Perform the process
HelpMsg('So why are you reading this? The action is up above '+chr(24)+'')
for I = 1 to lLoopCount
* Display some statistical fluff
@ lTop+1, lLeft+13 say I pict '999'
@ lTop+1, lLeft+21 say int(I/lLoopCount * 100) pict '999%'
* Graphically show the percentage
AdvanceBar(I/lLoopCount) && simple, eh?
next
ClosWindow()
return
*
procedure IsThatAll
*-----------------*
lIsT = 4
lIsL = 12
lIsB = lIsT+4
lIsR = lIsL+53
if iscolor()
lIsFrame = 'B+/B'
lIsHead = 'R+*/B'
lIsBody = 'G+/B'
else
lIsFrame = 'N/W'
lIsHead = 'W+*/W'
lIsBody = 'W+/W'
endif
OpenWindow(lIsT, lIsL, lIsB, lIsR, lIsFrame, lIsHead, lIsBody, 'NO!')
@ lIsT+1, lIsL+2 say "That's not all there is but that's the fun stuff."
@ lIsT+2, lIsL+2 say "Just browse around the source code and you'll find"
@ lIsT+3, lIsL+2 say "some interesting things. Have fun with it!"
HelpMsg('Press any key (well, you know, almost any)...')
inkey(0)
ClosWindow()
return
*
procedure DispLogo
*----------------*
setcolor(lLogo)
@ lLogoT, lLogoL clear to lLogoB, lLogoR
@ lLogoT+1, lLogoL+2 say ' TCMCLIP Demonstration Program '
@ lLogoT+2, lLogoL+2 say '───────────────────────────────'
@ lLogoT+3, lLogoL+2 say " Clipper Summer '87 Routines "
@ lLogoT+4, lLogoL+2 say ' '
@ lLogoT+5, lLogoL+2 say ' by Todd C. MacDonald '
@ lLogoT+6, lLogoL+2 say '───────────────────────────────'
@ lLogoT+7, lLogoL+2 say ' Placed in the Public Domain '
return
procedure EraseLogo
*-----------------*
private lLastColor
lLastColor=setcolor(lBackGrnd)
@ lLogoT, lLogoL, lLogoB, lLogoR box replicate(lBGchar, 9)
setcolor(lLastColor)
return
procedure ClosSystem
*------------------*
private lEndTime, lElapsed, lHours, lMins, lSecs
* Calculate elapsed time
lEndTime = time()
lElapsed=elaptime(lStartTime, lEndTime)
lHours=substr(lElapsed, 1, 2)
lHours=if(left(lHours,1)='0', right(lHours,1), lHours)
lHours=if(val(lHours) > 0, lHours+' Hour'+if(val(lHours)>1, 's ', ' '), '')
lMins=substr(lElapsed, 4, 2)
lMins=if(left(lMins,1)='0', right(lMins,1), lMins)
lMins=if(val(lMins) > 0, lMins+' Minute'+if(val(lMins)>1, 's ', ' ') , '')
lSecs=substr(lElapsed, 7, 2)
lSecs=if(left(lSecs,1)='0', right(lSecs,1), lSecs)
lSecs=if(val(lSecs) > 0, lSecs+' Second'+if(val(lSecs)>1, 's', '') , '')
* Display elapsed time and quit
OpenWindow(lCloseT, lCloseL, lCloseB, lCloseR, lClosFrame, lClosHead, lClosBody, '')
@ lCloseT+2, lCloseL+1 say CJustify('This program was active for:', lCloseR-lCloseL-1)
@ lCloseT+4, lCloseL+1 say CJustify(lHours+lMins+lSecs, lCloseR-lCloseL-1)
setcolor(GetColor(2))
@ lCloseT+6, lCloseL+1 say CJustify('Enjoy!', lCloseR-lCloseL-1)
return
*
* ────────────── Include the following routines in your source ──────────────
* MISCELLANEOUS PROCEDURES & FUNCTIONS
procedure Beep
*------------*
* Author: Todd C. MacDonald
* Syntax: Beep()
* Purpose: Produces a tone on the speaker.
*
tone(300,1)
return
function ValidFileN
*-----------------*
* Author: Todd C. MacDonald
* Syntax: ValidFileN( <expC1>, <expC2>, <expC2> )
* Where: <expC1> is the filename (excluding extension) to be validated
* <expC2> is the extension to append to <expC1> when testing for
* the files' existence in the current subdirectory
* <expC3> is a list of filenames in the form of "FILE1,FILE2,FILE3"
* to exclude as valid filenames
* Returns: True if the file name <expC1> adheres to DOS filename restrictions,
* does not exist in the current directory, and is not included in the
* list of filenames passed in <expC2>.
*
parameter lFileName, lExtension, lExclude
private I
lFileName = alltrim(lFileName)
for I = 1 to len(lFileName)
if substr(lFileName, I, 1) $'."/\[]:|<>+=;,' .or. asc(substr(lFileName, I, 1)) < 33
return .f.
endif
next
if file(lFileName+'.'+lExtension)
return .f.
endif
if (','+lFileName+',' $lExclude) .or. (len(lFileName) = 0)
return .f.
endif
return .t.
function ValidInkey
*-----------------*
* Author: Todd C. MacDonald
* Syntax: ValidInkey( <expC> )
* Where: <expC> is a string of valid characters
* Returns: The uppercased character representation of the key pressed if it is
* contained in <expC>; or Null ('') if the user pressed Esc.
*
parameters lKeySet
private lKey
lKey = inkey(0)
do while (.not. upper(chr(lKey)) $lKeySet) .and. (lKey <> kEsc)
lKey = inkey(0)
enddo
if lKey <> kEsc
return upper(chr(lKey))
else
return ''
endif
* STRING FUNCTIONS
function LeftPad
*--------------*
* Author: Todd C. MacDonald
* Syntax: LeftPad( <expC1>, <expC2>, <expN> )
* Where: <expC1> is a character string
* <expC2> is the character to pad <expC1> with
* <expN> is the length of the resulting string
* Returns: <expC1> with leading <expC2>'s in a field of <expN> length
*
parameters lString, lChar, lLen
lString=ltrim(rtrim(lString))
return replicate(lChar,lLen-len(lString))+lString
function ZeroFill
*---------------*
* Author: Todd C. MacDonald
* Syntax: ZeroFill( <expC>, <expN> )
* Where: <expC> is a character string
* <expN> is the length of the resulting string
* Returns: <expC> with leading zeros in a field of <expN> length
*
parameters lString, lLen
lString=ltrim(rtrim(lString))
return replicate('0',lLen-len(lString))+lString
function LJustify
*---------------*
* Author: Todd C. MacDonald
* Syntax: LJustify( <expC>, <expN> )
* Where: <expC> is a character string
* <expN> is the length of the resulting string
* Returns: <expC> left justified in a field of <expN> spaces
*
parameters lString, lLen
return lString+space(lLen-len(lString))
function RJustify
*---------------*
* Author: Todd C. MacDonald
* Syntax: RJustify( <expC>, <expN> )
* Where: <expC> is a character string
* <expN> is the length of the resulting string
* Returns: <expC> right justified in a field of <expN> spaces
*
parameters lString, lLen
return space(lLen-len(lString))+lString
function CJustify
*---------------*
* Author: Todd C. MacDonald
* Syntax: CJustify( <expC>, <expN> )
* Where: <expC> is a character string
* <expN> is the length of the resulting string
* Returns: <expC> centered in a field of <expN> spaces
*
parameters lString, lLen
lString=space(int((lLen-len(lString))/2))+lString
return lString+space(lLen-len(lString))
function NextAt
*-------------*
* Author: Todd C. MacDonald
* Syntax: NextAt( <expC1>, <expC2>, <expN> )
* Where: <expC1> is the character string to search for within <expC2>
* <expC2> is the character string to search
* <expN> is the position within <expC2> to begin the search
* Returns: A number corresponding to the position of <expC1> in <expC2> starting
* from postition <expN>.
*
parameters lTarget, lString, lStartPos
private lTempStr
lTempStr = right(lString, len(lString)-lStartPos+1)
lAtPos = at(lTarget, lTempStr)
return if(lAtPos <> 0, lStartPos+lAtPos-1, 0)
function Lotus2Chr
*----------------*
* Author: Todd C. MacDonald
* Syntax: Lotus2Chr( <expC> )
* Where: <expC> is a character string in the form of "\999\999\..."
* Returns: Lotus style printer setup string <expC> converted to a character
* string transmittable to the printer.
*
parameters lLotusStr
private lChrStr, lVal, lStartPos
lLotusStr = alltrim(lLotusStr)
lChrStr = ''
lStartPos = at('\', lLotusStr)
do while lStartPos <> 0
lEndPos = NextAt('\', lLotusStr, lStartPos+1)
if lEndPos <> 0
lChrStr = lChrStr + chr(val(substr(lLotusStr, lStartPos+1, lEndPos-lStartPos-1)))
else
lChrStr = lChrStr + chr(val(substr(lLotusStr, lStartPos+1, len(lLotusStr))))
endif
lStartPos = lEndPos
enddo
return lChrStr
* SCREEN RELATED PROCEDURES AND FUNCTIONS
procedure ReadGets
*----------------*
* Author: Todd C. MacDonald
* Syntax: ReadGets()
* Purpose: Normal Clipper READ except turn the cursor on before and off after.
*
set cursor on
read
set cursor off
return
function GetColor
*---------------*
* Author: Todd C. MacDonald
* Syntax: GetColor( <expN> )
* Where: <expN> is the logical position of the color in a SETCOLOR() string
* Returns: A string representing the current color (Standard, Enhanced, Border
* Background, Unselected) pointed to by <expN>.
*
parameters lColorPos
private lColorStr, I, lCommaPos1, lCommaPos2
lColorStr = setcolor()
lCommaPos1 = at(',', lColorStr)
if lColorPos = 1
return left(lColorStr, if(lCommaPos1 <> 0, lCommaPos1 - 1, len(lColorStr)))
else
for I = 3 to lColorPos
if lCommaPos1 = 0
exit
endif
lCommaPos1 = NextAt(',', lColorStr, lCommaPos1 + 1)
next
lCommaPos2 = NextAt(',', lColorStr, lCommaPos1 + 1)
return substr(lColorStr, lCommaPos1+1, if(lCommaPos2 <> 0, lCommaPos2 - 1, len(lColorStr)) - lCommaPos1)
endif
function GetFGClrNo
*-----------------*
* Author: Todd C. MacDonald
* Syntax: GetFGClrNo( <expN> )
* Where: <expN> is the logical position of the color in a SETCOLOR() string
* Returns: A number representing the current color (Standard, Enhanced, Border
* Background, Unselected) pointed to by <expN>. You can use this to
* feed Rick Whitt's SCRNPLAY functions.
*
parameters lColorPos
private lColorTable, lColor
lColorTable = 'N B G BG R RB GR W N+ B+ G+ BG+R+ RB+GR+W+ '
lColor = alltrim(strtran(GetColor(lColorPos), '*'))
lColor = if(at('/', lColor) <> 0, left(lColor, at('/', lColor)-1), lColor)
lColor = lColor + space(3-len(lColor))
return (at(lColor, lColorTable)-1)/3
function GetBGClrNo
*-----------------*
* Author: Todd C. MacDonald
* Syntax: GetFGClrNo( <expN> )
* Where: <expN> is the logical position of the color in a SETCOLOR() string
* Returns: A number representing the current color (Standard, Enhanced, Border
* Background, Unselected) pointed to by <expN>. You can use this to
* feed Rick Whitt's SCRNPLAY functions.
*
parameters lColorPos
private lColorTable, lColor
lColorTable = 'N B G BG R RB GR W N+ B+ G+ BG+R+ RB+GR+W+ '
lColor = alltrim(strtran(GetColor(lColorPos), '*'))
lColor = if(at('/', lColor) <> 0, right(lColor, len(lColor)-at('/', lColor)), lColor)
lColor = lColor + space(3-len(lColor))
return (at(lColor, lColorTable)-1)/3
function MakeBlink
*----------------*
* Author: Todd C. MacDonald
* Syntax: MakeBlink( <expN> )
* Where: <expN> is the logical position of the color in a SETCOLOR() string
* Returns: A string representing the current color (Standard, Enhanced, Border
* Background, Unselected) pointed to by <expN> with an '*' added to
* make the color blink.
*
parameter lColorPos
private lColorStr
lColorStr = GetColor(lColorPos)
return stuff(lColorStr, at('/', lColorStr), 0, '*')
procedure Center
*--------------*
* Author: Todd C. MacDonald
* Syntax: Center( <expN1>, <expN2>, <expN3>, <expC> )
* Where: <expN1> is the row
* <expN2> is the left column
* <expN3> is the right column
* <expC> is the string to center
* Purpose: Centers <expC> between the columns indicated by <expN2> and <expN3>
* on the line indicated by <expN1>.
*
parameters lRow, lLCol, lRCol, lMsg
@ lRow, lLCol+int((lRCol-lLCol+1-len(lMsg))/2) say lMsg
return
procedure InitMenu
*----------------*
* Author: Todd C. MacDonald
* Syntax: InitMenu( <expN1>, <expC1>, <expC2>,;
* <expN2>, <expN3>, <expN4>, <expN5> )
* Where: <expN1> is the number of options in the menu
* <expC1> is the SETCOLOR() type string of the unselected options
* <expC2> is the SETCOLOR() type string of the selected option
* <expN2> and <expN3> are the foreground and background attributes used
* to highlight the unselected options trigger letters
* <expN4> and <expN5> are the foreground and background attributes used
* to highlight the currently selected options' trigger letter.
* Purpose: Initializes the variables used by the MenuPrompt and MenuChoice
* procedures.
*
parameter lNbrItems, lNormal, lHilite, lSelectF, lSelectB, lSelectFHi, lSelectBHi
public aMnuRow[lNbrItems], aMnuCol[lNbrItems]
public aMnuPrompt[lNbrItems], aMnuSelect[lNbrItems], pMnuChars
public pMnuNbr, pMnuItem
public pMnuNormal, pMnuHilite, pMnuSelF, pMnuSelB, pMnuSelFHi, pMnuSelBHi
pMnuNbr = lNbrItems
pMnuItem = 1
pMnuChars = ''
pMnuNormal = lNormal
pMnuHilite = lHilite
pMnuSelF = lSelectF
pMnuSelB = lSelectB
pMnuSelFHi = lSelectFHi
pMnuSelBHi = lSelectBHi
return
procedure MenuPrompt
*------------------*
* Author: Todd C. MacDonald
* Syntax: InitMenu( <expN1>, <expN2>, <expC1>, <expN3> )
* Where: <expN1> is the row on which the menu prompt <expC1> is to appear
* <expN2> is the column at which the menu prompt <expC1> is to appear
* <expC1> is the menu prompt
* <expN3> is the position of the "trigger" letter within <expC1>
* Purpose: Initializes the variables used in the MenuChoice procedure.
*
parameters lRow, lCol, lPrompt, lSelectPos
aMnuRow[pMnuItem] = lRow
aMnuCol[pMnuItem] = lCol
aMnuPrompt[pMnuItem] = lPrompt
aMnuSelect[pMnuItem] = lSelectPos - 1
pMnuChars = pMnuChars + upper(substr(lPrompt, lSelectPos, 1))
pMnuItem = pMnuItem + 1
return
function MenuChoice
*-----------------*
* Author: Todd C. MacDonald
* Syntax: MenuChoice( <expN> )
* Where: <expN> is the number of prompt to highlight initially
* Purpose: Displays the prompts created by the MenuPrompt procedure and lets the
* user select an option either by highlighting it and pressing [Enter]
* or by typing the "trigger" letter.
* Returns: The number corresponding to the option selected (Zero if [Esc] was
* pressed).
* Notes: This procedure necessitates linking in the Rick Whitt's CHGATTR.OBJ
* file.
*
parameter lMnuItem
private lOrigColor, I
lOrigColor = setcolor(pMnuNormal)
for I = 1 to pMnuNbr
@ aMnuRow[I], aMnuCol[I] say aMnuPrompt[I]
chgattr(aMnuRow[I], aMnuCol[I]+aMnuSelect[I], aMnuRow[I], aMnuCol[I]+aMnuSelect[I], pMnuSelF, pMnuSelB)
next
do while .t.
setcolor(pMnuHilite)
@ aMnuRow[lMnuItem], aMnuCol[lMnuItem] say aMnuPrompt[lMnuItem]
chgattr(aMnuRow[lMnuItem], aMnuCol[lMnuItem]+aMnuSelect[lMnuItem], aMnuRow[lMnuItem], aMnuCol[lMnuItem]+aMnuSelect[lMnuItem], pMnuSelFHi, pMnuSelBHi)
if nextkey() <> kEnter
keyboard ''
endif
lMnuKey = inkey(0)
setcolor(pMnuNormal)
@ aMnuRow[lMnuItem], aMnuCol[lMnuItem] say aMnuPrompt[lMnuItem]
chgattr(aMnuRow[lMnuItem], aMnuCol[lMnuItem]+aMnuSelect[lMnuItem], aMnuRow[lMnuItem], aMnuCol[lMnuItem]+aMnuSelect[lMnuItem], pMnuSelF, pMnuSelB)
do case
case (lMnuKey = kDarrow) .or. (lMnuKey = kRarrow)
lMnuItem = lMnuItem + 1
if lMnuItem > pMnuNbr
lMnuItem = 1
endif
case (lMnuKey = kUarrow) .or. (lMnuKey = kLarrow)
lMnuItem = lMnuItem - 1
if lMnuItem < 1
lMnuItem = pMnuNbr
endif
case lMnuKey = kHome
lMnuItem = 1
case lMnuKey = kEnd
lMnuItem = pMnuNbr
case upper(chr(lMnuKey)) $pMnuChars
lMnuItem = at(upper(chr(lMnuKey)), pMnuChars)
keyboard chr(kEnter)
case lMnuKey = kEnter
setcolor(lOrigColor)
return lMnuItem
case lMnuKey = kEsc
setcolor(lOrigColor)
return 0
endcase
enddo
procedure InitBar
*---------------*
* Author: Todd C. MacDonald
* Syntax: InitBar( <expN1>, <expN2>, <expN3>, <expC1>, <expC2> ] )
* Where: <expN1> is the screen row to display the scale at
* <expN2> is the screen column to display the scale at
* <expN3> is the width (in characters) of the scale
* <expC1> is the color used for the scale (default: "W/N")
* <expC2> is the color used for the bar (default: "W+/N")
* Purpose: Initializes variables used by the AdvanceBar procedure and Displays a
* "scale" of length <expN3> at row <expN1>, column <expN2> in the color
* specified by <expC1>. Subsequent calls to AdvanceBar will cause the
* "bar" (displayed in the color specified by <expC2>) to advance
* reflecting the current percentage.
*
parameters lRow, lCol, lWidth, lScaleColr, lBarColor
public pBarRow, pBarCol, pBarWidth, pScaleColr, pBarColor, pBarStep
private lOrigColor
pBarRow = lRow
pBarCol = lCol
pBarWidth = lWidth
pScaleColr = if(pcount() > 3, lScaleColr, "W/N")
pBarColor = if(pcount() > 4, lBarColor, "W+/N")
pBarStep = 100 / pBarWidth / 100
lOrigColor = setcolor(pScaleColr)
@ pBarRow, pBarCol say replicate('░', pBarWidth)
setcolor(lOrigColor)
return
procedure AdvanceBar
*------------------*
* Author: Todd C. MacDonald
* Syntax: AdvanceBar( <expN> )
* Where: <expN> is a number less than or equal to 1
* Purpose: Used in conjunction with the InitBar procedure. Paints the bar on
* the scale reflecting the current percentage passed in as a parameter.
*
parameters lPercent
private lOrigColor
lOrigColor = setcolor(pBarColor)
if lPercent < 1
@ pBarRow, pBarCol say replicate('█', int(lPercent/pBarStep))
else
@ pBarRow, pBarCol say replicate('█', pBarWidth)
endif
setcolor(lOrigColor)
return
procedure ExplodeBox
*------------------*
* Author: Todd C. MacDonald
* Syntax: ExplodeBox( <expN1>, <expN2>, <expN3>, <expN4>, <expC> )
* Where: <expN1> is the top row
* <expN2> is the left column
* <expN3> is the bottom row
* <expN4> is the right column
* <expC> is a string of box drawing characters (same as @ BOX)
* Purpose: Displays a succession of boxes on the screen creating an exploding
* effect. The explosion stops when it reaches the borders specified
* by <expN1> through <expN4> (Top, Left, Bottom, Right, respectively).
* The characters used to draw the boxes are passed in <expC>.
*
parameters lTop, lLeft, lBottom, lRight, lFrame
private lXT, lXL, lXB, lXR, lTReached, lLReached
* Also references public variable pExpFactor, pExpDelay
* Determine top & bottom starting lines
lXT = lTop
lXB = lBottom
do while .t.
lXT = lXT + pExpFactor
lXB = lXB - pExpFactor
if lXT >= lXB
lXT = lXT - pExpFactor
lXB = lXB + pExpFactor
exit
endif
enddo
* Determine left & right starting columns
lXL = lLeft
lXR = lRight
do while .t.
lXL = lXL + pExpFactor * 2
lXR = lXR - pExpFactor * 2
if lXL >= lXR
lXL = lXL - pExpFactor * 2
lXR = lXR + pExpFactor * 2
exit
endif
enddo
* Explode the frame
store .f. to lTReached, lLReached
do while .not. (lTReached .and. lLReached)
@ lXT, lXL, lXB, lXR box lFrame
* decrement top, increment bottom
if lXT > lTop
lXT = lXT - pExpFactor
lXB = lXB + pExpFactor
else
lTReached = .t.
endif
* decrement left, increment right
if lXL > lLeft
lXL = lXL - pExpFactor * 2
lXR = lXR + pExpFactor * 2
else
lLReached = .t.
endif
for I = 1 to pExpDelay
next
enddo
return
procedure OpenWindow
*------------------*
* Author: Todd C. MacDonald
* Syntax: OpenWindow( <expN1>, <expN2>, <expN3>, <expN4>,;
* <expC1>, <expC2>, <expC3>, <expC4>,;
* [[ <expL1> ], <expL2> ] )
* Where: <expN1> is the top row
* <expN2> is the left column
* <expN3> is the bottom row
* <expN4> is the right column
* <expC1> is a SETCOLOR() string representing the color of the Frame
* <expC2> is a string representing the color of the Header
* <expC3> is a string representing the color of the Body of the window
* <expC4> is a string containing the text of the window header
* <expL1> is true to explode the window; false otherwise (overrides pExplode)
* <expL2> is true to paint a shadow; false otherwise (overrides pShadow)
* Purpose: Displays a window on the screen whose borders are specified by
* <expN1> through <expN4>. The colors of the window are specified in
* <expC1> through <expC3>. If <expL1> is true, the window will
* "explode" onto the screen. If the public variable pShadow is true, a
* "see-through" shadow will border the right-hand and bottom edges of
* the window.
* Notes: References the following public variables: pWindIndex, aWindT, aWindL,
* aWindL, aWindB, aWindR, aWindow, aWindColor, pWindFrame, pExplode,
* pShadow. This procedure necessitates linking in Rick Whitt's CHGATTR.OBJ
* file.
*
parameters lTop, lLeft, lBottom, lRight,;
lFrameColor, lHeaderColor, lWindowColor,;
lHeaderText, lExplode, lShadow
* Save region of screen to be written over
pWindIndex=pWindIndex+1
aWindT[pWindIndex]=lTop
aWindL[pWindIndex]=lLeft
aWindB[pWindIndex]=lBottom+if(lBottom+1 <= 24, 1, 0)
aWindR[pWindIndex]=lRight+if(lRight+2 <= 79, 2, if(lRight+1 <= 79, 1, 0))
aWindow[pWindIndex]=savescreen(aWindT[pWindIndex], aWindL[pWindIndex], aWindB[pWindIndex], aWindR[pWindIndex])
* Draw window
aWindColor[pWindIndex] = setcolor(lFrameColor)
if pExplode .and. if(pcount() > 8, lExplode, .t.)
ExplodeBox(lTop, lLeft, lBottom, lRight, pWindFrame)
else
@ lTop, lLeft, lBottom, lRight box pWindFrame
endif
* Paint shadow
if if(pcount() < 10, pShadow, lShadow)
if lRight+2 <= 79
chgattr(lTop+1, lRight+1, lBottom, lRight+2, 7, 0)
if lBottom+1 <= 24
chgattr(lBottom+1, lLeft+2, lBottom+1, lRight+2, 7, 0)
endif
elseif lRight+1 <= 79
chgattr(lTop+1, lRight+1, lBottom, lRight+1, 7, 0)
if lBottom+1 <= 24
chgattr(lBottom+1, lLeft+2, lBottom+1, lRight+1, 7, 0)
endif
elseif lBottom+1 <= 24
chgattr(lBottom+1, lLeft+2, lBottom+1, lRight, 7, 0)
endif
endif
* Display Header
setcolor(lHeaderColor)
if pcount() > 7
if len(lHeaderText) > 0
do Center with lTop, lLeft, lRight, lHeaderText
endif
endif
* Paint area inside window
setcolor(lWindowColor)
@ lTop+1, lLeft+1 clear to lBottom-1, lRight-1
return
procedure ClosWindow
*------------------*
* Author: Todd C. MacDonald
* Syntax: ClosWindow()
* Purpose: Erases the last window displayed on the screen using OpenWindow and
* restores the area of the screen beneath the window.
* Notes: References the following public variables: aWindColor, pWindIndex
* aWindT, aWindL, aWindB, aWindR, aWindow
*
* Reset previous color attributes
setcolor(aWindColor[pWindIndex])
* Restore contents of screen beneath the current window
restscreen(aWindT[pWindIndex], aWindL[pWindIndex],;
aWindB[pWindIndex], aWindR[pWindIndex], aWindow[pWindIndex])
pWindIndex=pWindIndex-1
return
procedure HelpMsg
*---------------*
* Author: Todd C. MacDonald
* Syntax: HelpMsg( <expC> )
* Where: <expC> is the message to be displayed
* Purpose: Displays <expC> centered on line 24 of the screen and highlights any
* portions of <expC> that are surrounded by the Ctrl-A character.
* Notes: References the following public variables: aHelpColor, pHelpHighF,
* pHelpHighB. This procedure necessitates linking in Rick Whitt's CHGATTR.OBJ
* file.
*
parameter lMsg
private I, lCtrlAPos, aStart[10], aStop[10], lCol, lOrigColor, J
* DETERMINE START & STOP HIGHLIGHT POSITIONS
I = 1
lCtrlAPos = at('', lMsg)
do while lCtrlAPos > 0
aStart[I] = lCtrlAPos
lMsg = stuff(lMsg, lCtrlAPos, 1, '')
lCtrlAPos = at('', lMsg)
aStop[I] = lCtrlAPos-1
lMsg = stuff(lMsg, lCtrlAPos, 1, '')
I = I + 1
lCtrlAPos = at('', lMsg)
enddo
* CALCULATE STARTING COLUMN
lCol = int((80-len(lMsg))/2)
lOrigColor = setcolor(pHelpColor)
@ 24, 0
@ 24, lCol say lMsg
for J = 1 to I-1
chgattr(24, lCol+aStart[J]-1, 24, lCol+aStop[J]-1, pHelpHighF, pHelpHighB)
next
setcolor(lOrigColor)
return
function Verify
*-------------*
* Author: Todd C. MacDonald
* Syntax: Verify( <expC> )
* Where: <expC> is a string at some point containing the string "y/n", "Y/n"
* or "y/N"
* Purpose: Displays <expC> centered on line 24 of the screen, highlights the
* "y/n" portion, and waits for the user to respond.
* Returns: True if user types 'Y', false if 'N' or [Esc]. Also will return the
* default logical value corresponding to the uppercased letter 'Y' or
* or 'N' if the user simply presses [Enter].
* Notes: References the following public variables: pHelpColor, pHelpHigh,
* pHelpHighF, pHelpHighB. This function necessitates linking in Rick
* Whitt's CHGATTR.OBJ file.
*
parameters lQuery
private lTop, lLeft, lBottom, lRight, lScrnBuf, lOrigColor
private lKey, lRetVal, lRow, lCol, lY, lN, lYpos, lNpos
lTop = 24
lLeft = 0
lBottom = 24
lRight = 79
* save area of screen beneath query & clear it
lScrnBuf=savescreen(lTop, lLeft, lBottom, lRight)
lOrigColor = setcolor(pHelpColor)
@ lTop, lLeft clear to lBottom, lRight
* display query centered in the given area
lRow = lTop+int((lBottom - lTop) / 2)
lCol = lLeft+int((lRight-lLeft+1-len(lQuery))/2)
@ lRow, lCol say lQuery
* wait for [Y], [N], [Enter], or [Esc] key to be pressed
lSlshPos = rat('/', lQuery)
lY=substr(lQuery, lSlshPos-1, 1)
lN=substr(lQuery, lSlshPos+1, 1)
lYpos=lCol + lSlshPos - 1 - 1
lNpos=lCol + lSlshPos + 1 - 1
lYes=.t.
lKey=0
set color to (pHelpHigh)
do while .t.
if lYes
@ lRow, lYpos say lY
@ lRow, lNpos say ' '
lYes=.f.
else
@ lRow, lNpos say lN
@ lRow, lYpos say ' '
lYes=.t.
endif
lKey = inkey(.2)
do case
case upper(chr(lKey)) = 'Y' .or. (lKey = 13 .and. lY = 'Y')
lRetVal=.t.
exit
case upper(chr(lKey)) = 'N' .or. lKey = 27 .or. (lKey = 13 .and. lN = 'N')
lRetVal=.f.
exit
endcase
enddo
* restore area of screen beneath query
restscreen(lTop, lLeft, lBottom, lRight, lScrnBuf)
setcolor(lOrigColor)
return lRetVal
procedure Error
*-------------*
* Author: Todd C. MacDonald
* Syntax: Error( <expC> )
* Where: <expC> is an error message
* Purpose: Opens an error window in the center of the screen and displays <expC>
* wordwrapped within the window. It then waits for the user to press
* [Esc].
* Notes: References the following public variables: pErrFrame, pErrHead,
* pErrBody
*
parameters lErrMsg
private lTop, lLeft, lBottom, lRight, lNumLines, lLine, lTextLine, lKey
private lScrnBuff
lTop=4
lLeft=18
lBottom=16
lRight=61
OpenWindow(lTop, lLeft, lBottom, lRight, pErrFrame, pErrHead, pErrBody,;
' E R R O R ')
* DISPLAY THE ERROR MESSAGE
lNumLines=mlcount(lErrMsg, lRight-lLeft-3)
for lLine = 1 to lNumLines
lTextLine=memoline(lErrMsg, lRight-lLeft-3, lLine)
@ lTop+1+lLine-1, lLeft+2 say lTextLine
next
lScrnBuff=savescreen(24, 0, 24, 79)
HelpMsg(' Press Esc to continue...')
beep()
beep()
* WAIT FOR [Esc]
lKey=0
do while lKey <> 27
lKey=inkey()
enddo
ClosWindow()
restscreen(24, 0, 24, 79, lScrnBuff)
return
* ERROR RECOVERY FUNCTIONS
function Print_Error
*------------------*
* Author: Todd C. MacDonald
* Purpose: Dresses up Clippers PRINT_ERROR function.
*
parameters lName, lLine
set device to screen
keyboard '' && clear keyboard buffer
beep()
if Verify('PRINTER NOT READY! Continue? [Y/n] (pressing "N" will abort this program)')
set device to printer
return .t.
else
HelpMsg('PROGRAM ABORTED!')
close databases
set cursor on
quit
endif